package com.yanqu.road.logic.xlogic.rank.season;

import com.yanqu.road.entity.enums.eSeasonRewardType;
import com.yanqu.road.entity.rank.xrank.XSeasonUserRank;
import com.yanqu.road.logic.bussiness.rank.XRankBussiness;
import com.yanqu.road.logic.pb.XRankPb;
import com.yanqu.road.logic.sort.XSeasonJinBiaoPeakRankSort;
import com.yanqu.road.logic.sort.XSeasonJinBiaoScoreRankSort;
import com.yanqu.road.logic.sort.XSeasonUserRankSort;
import com.yanqu.road.logic.xlogic.base.BaseXMap;
import com.yanqu.road.logic.xlogic.base.IChannelSeasonMaxRank;
import com.yanqu.road.pb.cross3.activity.XRankProto;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 个人赛季榜
 */
public class XSeasonUserRankMap extends BaseXMap {

    private IChannelSeasonMaxRank maxRank;

    public XSeasonUserRankMap(String dbName, String tableName, IChannelSeasonMaxRank maxRank) {
        super(dbName, tableName);
        this.maxRank = maxRank;
    }

    /**
     * 榜单    （系统ID，赛季ID，类型，范围，数据）
     */
    private final Map<Integer, Map<Integer, Map<Integer, Map<String, XSeasonUserRankListModel>>>> userRankMap = new ConcurrentHashMap<>();

    /**
     * 待上传榜单    （系统ID，赛季ID，类型，范围，玩家ID，数据）
     */
    private final Map<Integer, Map<Integer, Map<Integer, Map<String, Map<Long, XSeasonUserRank>>>>> syncCache = new ConcurrentHashMap<>();

    /**
     * 拿榜单
     */
    public XSeasonUserRankListModel getUserRankListModel(int systemId, int seasonId, int type, String rangeKey) {
        synchronized (userRankMap) {
            userRankMap.putIfAbsent(systemId, new ConcurrentHashMap<>());
            userRankMap.get(systemId).putIfAbsent(seasonId, new ConcurrentHashMap<>());
            userRankMap.get(systemId).get(seasonId).putIfAbsent(type, new ConcurrentHashMap<>());
            Map<String, XSeasonUserRankListModel> map = userRankMap.get(systemId).get(seasonId).get(type);
            if (!map.containsKey(rangeKey)) {
                // 读库
                List<XSeasonUserRank> rankList = XRankBussiness.getXSeasonUserRankList(dbName, tableName, systemId, seasonId, type, rangeKey);
                XSeasonUserRankListModel model = null;
                if (type == eSeasonRewardType.WasheScoreRank.getIntValue()) {
                    model = new XSeasonUserRankListModel(dbName, tableName, systemId, seasonId, type, rangeKey, maxRank.getChannelSeasonMaxRank(systemId, seasonId, type, rangeKey), new XSeasonUserRankSort());
                } else if (type == eSeasonRewardType.JinBiaoScoreRank.getIntValue()) {
                    model = new XSeasonUserRankListModel(dbName, tableName, systemId, seasonId, type, rangeKey, maxRank.getChannelSeasonMaxRank(systemId, seasonId, type, rangeKey), new XSeasonJinBiaoScoreRankSort());
                } else if (type == eSeasonRewardType.JinBiaoPeakRank.getIntValue()) {
                    model = new XSeasonUserRankListModel(dbName, tableName, systemId, seasonId, type, rangeKey, maxRank.getChannelSeasonMaxRank(systemId, seasonId, type, rangeKey), new XSeasonJinBiaoPeakRankSort());
                }
                if(null != model) {
                    model.initByRankList(new LinkedList<>(rankList));
                    map.put(rangeKey, model);
                }
            }
            return map.get(rangeKey);
        }
    }

    /**
     * 榜单变更
     */
    public XSeasonUserRankChangeResult userRankChange(XSeasonUserRank userRank, XSeasonUserRankChangeParam param) {

        XSeasonUserRankChangeResult changeResult = getUserRankListModel(userRank.getSystemId(), userRank.getSeasonId(), userRank.getConditionType(), userRank.getRangeKey())
                .rankChange(userRank, param);

        /* 暂时全量
        // 需要同步 && 增量 && 新上榜  =>  设置下次全量同步
        if (param.isNeedSync() && param.isUpdateBaseInfo() && changeResult.isNewInRank()) {
            // XUserBaseInfoLogic.setNextAll(userRank.getActivityId(), userRank.getConditionType(), userRank.getUserId());
        }
        */

        // 需要同步 && 榜单有变动  => 添加同步数据
        if (param.isNeedSync() && changeResult.isChange()) {
            addSyncCache(userRank);
        }

        return changeResult;
    }

    /**
     * 获取全部榜单
     */
    public Map<Integer, Map<Integer, Map<Integer, Map<String, XSeasonUserRankListModel>>>> getUserRankMap() {
        return userRankMap;
    }

    /**
     * 添加待同步榜单
     */
    private void addSyncCache(XSeasonUserRank rank) {
        synchronized (syncCache) {
            syncCache.putIfAbsent(rank.getSystemId(), new ConcurrentHashMap<>());
            syncCache.get(rank.getSystemId()).putIfAbsent(rank.getSeasonId(), new ConcurrentHashMap<>());
            syncCache.get(rank.getSystemId()).get(rank.getSeasonId()).putIfAbsent(rank.getConditionType(), new ConcurrentHashMap<>());
            syncCache.get(rank.getSystemId()).get(rank.getSeasonId()).get(rank.getConditionType()).putIfAbsent(rank.getRangeKey(), new ConcurrentHashMap<>());
            Map<Long, XSeasonUserRank> rankMap = syncCache.get(rank.getSystemId()).get(rank.getSeasonId()).get(rank.getConditionType()).get(rank.getRangeKey());
            rankMap.put(rank.getUserId(), rank);
        }
    }

    /**
     * 获取待同步榜单 并清空
     */
    public List<XRankProto.XSeasonUserRankListMsg.Builder> getSyncCacheAndClear(boolean useUpdateMsg) {
        Map<Integer, Map<Integer, Map<Integer, Map<String, Map<Long, XSeasonUserRank>>>>> tmpCache;
        synchronized (syncCache) {
            if (syncCache.isEmpty()) return new ArrayList<>();
            tmpCache = new HashMap<>(syncCache);
            syncCache.clear();
        }
        List<XRankProto.XSeasonUserRankListMsg.Builder> resultList = new ArrayList<>();
        for (Map.Entry<Integer, Map<Integer, Map<Integer, Map<String, Map<Long, XSeasonUserRank>>>>> systemEntry : tmpCache.entrySet()) {
            int systemId = systemEntry.getKey();
            Map<Integer, Map<Integer, Map<String, Map<Long, XSeasonUserRank>>>> seasonMap = systemEntry.getValue();
            for (Map.Entry<Integer, Map<Integer, Map<String, Map<Long, XSeasonUserRank>>>> seasonEntry : seasonMap.entrySet()) {
                int seasonId = seasonEntry.getKey();
                Map<Integer, Map<String, Map<Long, XSeasonUserRank>>> typeMap = seasonEntry.getValue();
                for (Map.Entry<Integer, Map<String, Map<Long, XSeasonUserRank>>> typeEntry : typeMap.entrySet()) {
                    int type = typeEntry.getKey();
                    Map<String, Map<Long, XSeasonUserRank>> rangeMap = typeEntry.getValue();
                    for (Map.Entry<String, Map<Long, XSeasonUserRank>> rangeEntry : rangeMap.entrySet()) {
                        String rangeKey = rangeEntry.getKey();
                        Map<Long, XSeasonUserRank> rankMap = rangeEntry.getValue();
                        if (rankMap.isEmpty()) {
                            continue;
                        }
                        resultList.add(XRankPb.parseXSeasonUserRankListMsg(systemId, seasonId, type, rangeKey, new ArrayList<>(rankMap.values()), useUpdateMsg));
                    }
                }
            }
        }
        return resultList;
    }

    @Override
    public void save() {
        for (Map<Integer, Map<Integer, Map<String, XSeasonUserRankListModel>>> value : getUserRankMap().values()) {
            for (Map<Integer, Map<String, XSeasonUserRankListModel>> value2 : value.values()) {
                for (Map<String, XSeasonUserRankListModel> value3 : value2.values()) {
                    for (XSeasonUserRankListModel model : value3.values()) {
                        model.save();
                    }
                }
            }
        }
    }

    @Override
    public void loadDb(Object param) {

    }
}
